package org.filetransfer.file_transfer_java_backend.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.ServletRequest;
import org.filetransfer.file_transfer_java_backend.entity.File;
import org.filetransfer.file_transfer_java_backend.service.FilePreviewService;
import org.filetransfer.file_transfer_java_backend.service.ShareItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/api/preview")
public class FilePreviewController {

    @Autowired
    private FilePreviewService filePreviewService;

    @Autowired
    private ShareItemService shareItemService;

    @GetMapping("/{code}/{md5}")
    @Operation(summary = "获取文件预览信息", 
               description = "根据分享码和文件MD5获取文件预览信息，支持图片、文本、压缩包等多种文件类型")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "预览信息获取成功"),
        @ApiResponse(responseCode = "404", description = "文件不存在")
    })
    public ResponseEntity<Map<String, Object>> getFilePreview(
            @Parameter(description = "分享码", required = true) @PathVariable String code,
            @Parameter(description = "文件MD5值", required = true) @PathVariable String md5) {
        
        try {
            Map<String, Object> previewData = filePreviewService.getFilePreview(code, md5);
            return ResponseEntity.ok(previewData);
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }

    @GetMapping("/stream/{code}/{md5}/{fileName}")
    @Operation(summary = "流媒体预览", 
               description = "为视频和音频文件提供流媒体预览支持")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "流媒体数据"),
        @ApiResponse(responseCode = "404", description = "文件不存在"),
        @ApiResponse(responseCode = "416", description = "请求范围不满足")
    })
    public ResponseEntity<InputStreamResource> streamFile(
            @Parameter(description = "分享码", required = true) @PathVariable String code,
            @Parameter(description = "文件MD5值", required = true) @PathVariable String md5,
            @Parameter(description = "文件名", required = true) @PathVariable String fileName,
            @RequestHeader(value = "Range", required = false) String rangeHeader,
            ServletRequest request) throws FileNotFoundException {
        
        Optional<File> fileOptional = shareItemService.getShareItemFile(code, md5);
        if (fileOptional.isEmpty()) {
            return ResponseEntity.notFound().build();
        }

        File fileInfo = fileOptional.get();
        String filePath = fileInfo.getFilePath();
        long fileSize = fileInfo.getFileSize();

        // 处理Range请求（用于视频/音频流媒体播放）
        if (rangeHeader != null && rangeHeader.startsWith("bytes=")) {
            return handleRangeRequest(filePath, fileSize, rangeHeader, fileName);
        }

        // 普通请求
        FileInputStream fileInputStream = new FileInputStream(filePath);
        InputStreamResource resource = new InputStreamResource(fileInputStream);

        String mimeType = getContentType(fileName);
        
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + fileName + "\"")
                .contentType(MediaType.parseMediaType(mimeType))
                .contentLength(fileSize)
                .body(resource);
    }

    @GetMapping("/thumbnail/{code}/{md5}")
    @Operation(summary = "获取缩略图", 
               description = "为图片文件生成缩略图")
    @ApiResponses({
        @ApiResponse(responseCode = "200", description = "缩略图数据"),
        @ApiResponse(responseCode = "404", description = "文件不存在"),
        @ApiResponse(responseCode = "400", description = "不支持的文件类型")
    })
    public ResponseEntity<Map<String, Object>> getThumbnail(
            @Parameter(description = "分享码", required = true) @PathVariable String code,
            @Parameter(description = "文件MD5值", required = true) @PathVariable String md5,
            @Parameter(description = "缩略图宽度", required = false) @RequestParam(defaultValue = "200") int width,
            @Parameter(description = "缩略图高度", required = false) @RequestParam(defaultValue = "200") int height) {
        
        try {
            // 这里可以扩展实现真正的缩略图生成功能
            Map<String, Object> previewData = filePreviewService.getFilePreview(code, md5);
            
            // 如果是图片类型，可以在这里添加缩略图生成逻辑
            if ("image".equals(previewData.get("type"))) {
                Map<String, Object> thumbnailInfo = Map.of(
                    "width", width,
                    "height", height,
                    "message", "缩略图功能待实现，当前返回原图预览"
                );
                previewData.put("thumbnail", thumbnailInfo);
                return ResponseEntity.ok(previewData);
            } else {
                return ResponseEntity.badRequest().body(
                    Map.of("error", "该文件类型不支持缩略图生成")
                );
            }
        } catch (RuntimeException e) {
            return ResponseEntity.notFound().build();
        }
    }

    /**
     * 处理Range请求，用于流媒体播放
     */
    private ResponseEntity<InputStreamResource> handleRangeRequest(
            String filePath, long fileSize, String rangeHeader, String fileName) throws FileNotFoundException {
        
        // 解析Range头
        String range = rangeHeader.substring(6); // 移除 "bytes="
        String[] ranges = range.split("-");
        long start = 0;
        long end = fileSize - 1;

        if (ranges.length >= 1 && !ranges[0].isEmpty()) {
            start = Long.parseLong(ranges[0]);
        }
        if (ranges.length >= 2 && !ranges[1].isEmpty()) {
            end = Long.parseLong(ranges[1]);
        }

        // 验证范围
        if (start > end || start >= fileSize) {
            return ResponseEntity.status(416).build(); // Range Not Satisfiable
        }

        long contentLength = end - start + 1;
        
        // 创建文件输入流并跳过到指定位置
        FileInputStream fileInputStream = new FileInputStream(filePath);
        try {
            fileInputStream.skip(start);
        } catch (Exception e) {
            return ResponseEntity.status(500).build();
        }

        InputStreamResource resource = new InputStreamResource(fileInputStream);
        String mimeType = getContentType(fileName);

        return ResponseEntity.status(206) // Partial Content
                .header(HttpHeaders.CONTENT_RANGE, String.format("bytes %d-%d/%d", start, end, fileSize))
                .header(HttpHeaders.ACCEPT_RANGES, "bytes")
                .header(HttpHeaders.CONTENT_DISPOSITION, "inline; filename=\"" + fileName + "\"")
                .contentType(MediaType.parseMediaType(mimeType))
                .contentLength(contentLength)
                .body(resource);
    }

    /**
     * 根据文件名获取Content-Type
     */
    private String getContentType(String fileName) {
        String extension = getFileExtension(fileName).toLowerCase();
        
        return switch (extension) {
            case "mp4" -> "video/mp4";
            case "avi" -> "video/x-msvideo";
            case "mkv" -> "video/x-matroska";
            case "mov" -> "video/quicktime";
            case "wmv" -> "video/x-ms-wmv";
            case "flv" -> "video/x-flv";
            case "webm" -> "video/webm";
            case "mp3" -> "audio/mpeg";
            case "wav" -> "audio/wav";
            case "flac" -> "audio/flac";
            case "aac" -> "audio/aac";
            case "ogg" -> "audio/ogg";
            case "wma" -> "audio/x-ms-wma";
            case "jpg", "jpeg" -> "image/jpeg";
            case "png" -> "image/png";
            case "gif" -> "image/gif";
            case "bmp" -> "image/bmp";
            case "webp" -> "image/webp";
            case "svg" -> "image/svg+xml";
            case "pdf" -> "application/pdf";
            case "txt" -> "text/plain";
            case "html" -> "text/html";
            case "css" -> "text/css";
            case "js" -> "application/javascript";
            case "json" -> "application/json";
            case "xml" -> "application/xml";
            default -> "application/octet-stream";
        };
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String fileName) {
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex == -1) {
            return "";
        }
        return fileName.substring(lastDotIndex + 1);
    }
}
